package com.allwees.bs.c.module.user.service.impl;

import com.allwees.bs.c.module.ops.entity.CouponDefEntity;
import com.allwees.bs.c.module.ops.repository.CouponDefRepository;
import com.allwees.bs.c.module.ops.service.PointActiveDefUseService;
import com.allwees.bs.c.module.ops.service.UserCouponService;
import com.allwees.bs.c.module.user.constant.EPointQueryType;
import com.allwees.bs.c.module.user.dao.UserPointDao;
import com.allwees.bs.c.module.user.entity.UserPointEntity;
import com.allwees.bs.c.module.user.entity.UserPointLogEntity;
import com.allwees.bs.c.module.user.repository.UserPointLogRepository;
import com.allwees.bs.c.module.user.service.UserPointService;
import com.allwees.bs.core.model.coupon.constant.PointChangeTypeEnum;
import com.allwees.bs.core.modelbase.page.PageParams;
import com.allwees.bs.core.modelbase.page.PaginateDTO;
import com.allwees.core.common.constant.EDelete;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * @author mouhaining
 * @since 2020-05-21 09:32
 */
@Slf4j
@Service
public class UserPointServiceImpl implements UserPointService {

    @Resource
    private UserPointDao userPointDao;

    @Autowired
    private UserPointLogRepository userPointLogRepository;

    @Autowired
    private UserCouponService userCouponService;

    @Autowired
    private PointActiveDefUseService pointActiveDefUseService;

    @Autowired
    private CouponDefRepository couponDefRepository;


    /**
     * 注册创建积分账号
     *
     * @param userUuid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserPointEntity create(String userUuid) {
        UserPointEntity userPoint = userPointDao.findOneByField("user_uuid",userUuid);
        if (userPoint != null) {
            return userPoint;
        }
        log.info(">>> create user point uuid[uuid:{}]", userUuid);
        userPoint = new UserPointEntity();
        userPoint.setUserUuid(userUuid);
        userPoint.setValue(BigDecimal.ZERO);
        userPointDao.create(userPoint);
        return userPoint;
    }

    @Override
    public List<UserPointEntity> findAllByUserUuid(String userUuid) {
        return userPointDao.findAllByUserUuid(userUuid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pointExchangeCoupon(String userUuid, String couponDefUuid) {
        Assert.hasLength(couponDefUuid, "coupondef uuid is not be null");

        CouponDefEntity couponDef = couponDefRepository.getByUuid(couponDefUuid);
        Assert.notNull(couponDef, "coupondef is not found");

        UserPointEntity userPoint = userPointDao.findOneByField("user_uuid",userUuid);
        Assert.isTrue(userPoint.getValue().compareTo(couponDef.getPointDeductAmt()) >= 0, "user point is insufficient");

        userCouponService.receive(userUuid, couponDefUuid);

        pointActiveDefUseService.use(userUuid, couponDef.getPointDeductAmt(), PointChangeTypeEnum.SYSTEM_EXCHANGE);
    }

    @Override
    public UserPointEntity getPoint(String userUuid) {
        return userPointDao.findOneByField("user_uuid",userUuid);
    }

    @Override
    public PaginateDTO<UserPointLogEntity> page(String userUuid, EPointQueryType queryType, PageParams pageParams) {
        Assert.isTrue(userUuid != null,"user uuid shoud not be blank");
        if (EPointQueryType.HIS.equals(queryType)) {
            UserPointLogEntity critiria = new UserPointLogEntity();
            critiria.setIsDeleted(EDelete.UNDELETED.value());
            critiria.setUserUuid(userUuid);
            Page<UserPointLogEntity> page = userPointLogRepository.findAll(Example.of(critiria), pageParams.toPageable());
            PaginateDTO<UserPointLogEntity> dto = PaginateDTO.of(page.getTotalElements(), page.getContent().size(), pageParams);
            return dto.setResults(page.getContent());
        }
        return PaginateDTO.of(0, 0, pageParams);
    }
}
